<?php
/**
 * Created by PhpStorm.
 * User: guokunsheng
 * Date: 2021/2/22
 * Time: 下午4:33
 */

namespace app\common\lib;

use FileConsumer;
use SensorsAnalytics;
use think\Env;
use think\Log;

/**
 * 神策打点
 * @doc https://manual.sensorsdata.cn/sa/latest/tech_sdk_server_php-17567186.html
 * Class SensorsData
 * @package app\common\lib
 */
class SensorsData
{
    private static $instance;

    private function __construct()
    {
    }

    /**
     * 获取一个神策数据SDK实例
     * @doc https://manual.sensorsdata.cn/sa/latest/tech_sdk_server_php-17567186.html#id-.PHPSDKv1.13-%E5%9C%A8%E7%A8%8B%E5%BA%8F%E4%B8%AD%E5%88%9D%E5%A7%8B%E5%8C%96SDK
     * @return SensorsAnalytics
     */
    private static function getInstance()
    {
        if (!(self::$instance instanceof SensorsAnalytics))
        {
            # 打点文件路径，查看env配置
            $envPath = Env::get('sensorsdata.path', '');
            if ($envPath === '')
            {
                # 默认存放在runtime/sensorsdata-log/
                $path = RUNTIME_PATH . 'sensorsdata-log' . DS;
            } else
            {
                $path = $envPath;
            }
            !is_dir($path) && mkdir($path, 0755, true);
            # 初始化一个 Consumer，用于数据发送
            $consumer = new FileConsumer($path . 'collect_log.' . date('Ymd'));
            # 使用 Consumer 来构造 SensorsAnalytics 对象
            self::$instance = new SensorsAnalytics($consumer);
        }
        return self::$instance;
    }

    /**
     * 事件打点
     * @doc https://manual.sensorsdata.cn/sa/latest/tech_sdk_server_php-17567186.html#id-.PHPSDKv1.13-%E8%BF%BD%E8%B8%AA%E4%BA%8B%E4%BB%B6
     * @param string $distinct_id 用户标识
     * @param bool $is_login_id 是否为登录用户id
     * @param string $event_name 事件名
     * @param array $data 打点数据
     */
    public static function track($distinct_id = '', $is_login_id = true, $event_name = 'EventName', $data = []): void
    {
        if (self::getSwitchStatus())
        {
            try
            {
                self::getInstance()->track($distinct_id, $is_login_id, $event_name, $data);
            }
            catch (\Exception $e)
            {
                Log::write('神策打点失败：$distinct_id=' . $distinct_id . ' $is_login_id=' . $is_login_id . ' $event_name=' . $event_name . ' $data=' . json_encode($data, true) . ' 错误信息：' . $e->getMessage(), 'error', true);
            }
        }
    }

    /**
     * 设置用户属性
     * @doc https://manual.sensorsdata.cn/sa/latest/tech_sdk_server_php-17567186.html#id-.PHPSDKv1.13-%E8%AE%BE%E7%BD%AE%E7%94%A8%E6%88%B7%E5%B1%9E%E6%80%A7
     * @param string $distinct_id 用户标识
     * @param bool $is_login_id 是否为登录用户id
     * @param array $data 用户数据
     * @param string $dataType [set|set_once|unset] 设置类型 set=>设置属性、set_once=>初次设置属性、unset=>删除不需要的属性
     */
    public static function profile($distinct_id = '', $is_login_id = true, $data = [], $dataType = 'set'): void
    {
        if (self::getSwitchStatus())
        {
            try
            {
                if (!empty($data))
                {
                    switch ($dataType)
                    {
                        /**
                         * 对于不再需要的用户属性，可以通过 `profile_unset()` 接口将属性删除。
                         */
                        case 'unset':
                            self::getInstance()->profile_unset($distinct_id, true, $data);
                            break;
                        /**
                         * @desc 记录初次设定的属性 例如 注册时间、用户渠道 等
                         * @doc https://manual.sensorsdata.cn/sa/latest/tech_sdk_server_php-17567186.html#id-.PHPSDKv1.13-%E8%AE%B0%E5%BD%95%E5%88%9D%E6%AC%A1%E8%AE%BE%E5%AE%9A%E7%9A%84%E5%B1%9E%E6%80%A7
                         */
                        case 'set_once':
                            self::getInstance()->profile_set_once($distinct_id, true, $data);
                            break;
                        default:
                            self::getInstance()->profile_set($distinct_id, true, $data);
                            break;
                    }
                }
            }
            catch (\Exception $e)
            {
                Log::write('神策用户属性设置失败：$distinct_id=' . $distinct_id . ' $is_login_id=' . $is_login_id . ' $data=' . json_encode($data, true) . ' 错误信息：' . $e->getMessage(), 'error', true);
            }
        }
    }

    /**
     * 用户注册/登录
     * @param $uid int 用户id
     * @param $anonymous_id string 匿名id
     */
    public static function signup($uid, $anonymous_id)
    {
        if (self::getSwitchStatus())
        {
            try
            {
                self::getInstance()->track_signup($uid, $anonymous_id);
            }
            catch (\Exception $e)
            {
                Log::write('神策打点失败：$uid=' . $uid . ' $anonymous_id=' . $anonymous_id . ' 错误信息：' . $e->getMessage(), 'error', true);
            }
        }
    }

    /**
     * 设置用户属性(记录初次设定的属性)
     * @doc
     * @param string $distinct_id 用户标识
     * @param bool $is_login_id 是否为登录用户id
     * @param array $data 用户数据
     */
    public static function profile_once($distinct_id = '', $is_login_id = true, $data = [])
    {
        if (self::getSwitchStatus())
        {
            try
            {
                if (!empty($data))
                {
                    self::getInstance()->profile_set_once($distinct_id, true, $data);
                }
            }
            catch (\Exception $e)
            {
                Log::write('神策用户属性设置失败：$distinct_id=' . $distinct_id . ' $is_login_id=' . $is_login_id . ' $data=' . json_encode($data, true) . ' 错误信息：' . $e->getMessage(), 'error', true);
            }
        }
    }

    /**
     * 应用响应结束时，关闭神策打点
     */
    public static function close(): void
    {
        if (self::getSwitchStatus())
        {
            try
            {
                self::getInstance()->close();
            }
            catch (\Exception $e)
            {
                Log::write('神策打点关闭失败：' . $e->getMessage(), 'error', true);
            }
        }
    }

    /**
     * 检查神策打点开关是否开启
     * @desc 环境变量开关有值，且header头中有distinct-id
     * @return bool
     */
    private static function getSwitchStatus()
    {
        // 只要不为空字符串就表示开启
        return Env::get('sensorsdata.switch', '') !== '';
    }
}
